#pragma once
#include <iostream>
#include<cerrno>
#include<cstring>
#include<cstdlib>
#include<string>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<sys/types.h>
using namespace std;
const char *pathname = "/home/xat";
const int proj_id = 0x66;
const int defaultsize = 4096;
std::string ToHex(key_t k)
{
    char buffer[1024]; 
    snprintf(buffer,sizeof(buffer),"0x%x",k);
    return buffer;
}
key_t GetshmKeyOrDie()
{
    key_t k = ftok(pathname,proj_id);
    if(k<0)
    {
        std::cerr<<"ftok error:"<<errno<<"error string:"<<strerror(errno)<<std::endl;
        exit(1);
    }
    return k;

}
int CreateShmOrDie(key_t key,int size,int flag)
{
    int shmid = shmget(key,size,flag);
    if(shmid < 0)
    {
        cerr<<"获取共享内存失败,错误码 :"<<errno<<"报错:"<<strerror(errno)<<endl;
        exit(2);
    }
    return shmid;
}
int Createshm(key_t key,int size)
{
    return CreateShmOrDie(key,size,IPC_CREAT|IPC_EXCL|0666);
}
int Getshm(key_t key,int size)
{
    return CreateShmOrDie(key,size,IPC_CREAT);
}
void DeleteShm(int shmid)
{
    int n = shmctl(shmid,IPC_RMID,nullptr);
    if(n<0)
    {
        cerr<<"删除共享内存失败,错误码 :"<<errno<<"报错:"<<strerror(errno)<<endl;
    }
    else
    {
        cout<<"共享内存删除成功,shmid:"<<shmid<<endl;
    }
}

// void shmDebug(int shmid)
// {
//     struct shmid_ds shmds;
//     int n = shmctl(shmid,IPC_STAT,&shmds);
//     if(n<0)
//     {
//         cerr<<"shmctl error"<<endl;
//         return;
//     }
//     cout << "shmds.shm_segsz: " << shmds.shm_segsz << endl;
//     cout << "shmds.shm_nattch:" << shmds.shm_nattch << endl;
//     cout << "shmds.shm_ctime:" << shmds.shm_ctime << endl;
//     cout << "shmds.shm_perm.__key:" << ToHex(shmds.shm_perm.__key) << endl;
// }


//挂接
void *shmAttach(int shmid)
{
    void *addr = shmat(shmid,nullptr,0);
    if((long long int)addr == -1)
    {
        cerr<<"挂接失败,错误码:"<<errno<<"报错:"<<strerror(errno)<<endl;
        return nullptr;
    }
    return addr;
}


//去关联
void shmDetach(void *addr)
{
    int n = shmdt(addr);
    if(n<0)
    {
        cerr<<"去关联失败，错误码:"<<errno<<"报错："<<strerror(errno)<<endl;
    }
}